home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libg++ / src / Fix.h < prev    next >
C/C++ Source or Header  |  1994-06-28  |  11KB  |  514 lines

  1. // -*- C++ -*-
  2. // Fix.h : variable length fixed point data type 
  3. //
  4.  
  5. #ifndef _Fix_h
  6. #ifdef __GNUG__
  7. #pragma interface
  8. #endif
  9. #define _Fix_h 1
  10.  
  11. #include <stream.h>
  12. #include <std.h>
  13. #include <stddef.h>
  14. #include <Integer.h>
  15. #include <builtin.h>
  16.  
  17. class Fix
  18. {
  19.   struct Rep                    // internal Fix representation
  20.   {
  21.     _G_uint16_t len;        // length in bits
  22.     _G_uint16_t siz;        // allocated storage
  23.     _G_int16_t  ref;        // reference count
  24.     _G_uint16_t s[1];        // start of ushort array represention
  25.   };
  26.  
  27. public:
  28.  
  29.   typedef void (*PEH)(Rep*);
  30.  
  31. private:
  32.  
  33.   Rep*          rep;
  34.  
  35.           Fix(Rep*);
  36.                   Fix(int, const Rep*);
  37.  
  38.   void          unique();
  39.  
  40.   static const _G_uint16_t min_length =     1;
  41.   static const _G_uint16_t max_length = 65535;
  42.   static const double min_value  =  -1.0;
  43.   static const double max_value  =   1.0;
  44.  
  45.   static _G_uint16_t   default_length;
  46.   static int       default_print_width;
  47.   static Rep      Rep_0;
  48.   static Rep       Rep_m1;
  49.   static Rep       Rep_quotient_bump;
  50.  
  51.   // internal class functions
  52.   static void      mask(Rep*);
  53.   static int      compare(const Rep*, const Rep* = &Rep_0);
  54.  
  55.   static Rep*      new_Fix(_G_uint16_t);
  56.   static Rep*      new_Fix(_G_uint16_t, const Rep*);
  57.   static Rep*      new_Fix(_G_uint16_t, double);
  58.  
  59.   static Rep*      copy(const Rep*, Rep*);
  60.   static Rep*      negate(const Rep*, Rep* = NULL);
  61.   static Rep*      add(const Rep*, const Rep*, Rep* = NULL);
  62.   static Rep*      subtract(const Rep*, const Rep*, Rep* = NULL);
  63.   static Rep*      multiply(const Rep*, const Rep*, Rep* = NULL);
  64.   static Rep*      multiply(const Rep*, int, Rep* = NULL);
  65.   static Rep*      divide(const Rep*, const Rep*, Rep* = NULL,
  66.              Rep* = NULL);
  67.   static Rep*      shift(const Rep*, int, Rep* = NULL);
  68.  
  69.   static one_arg_error_handler_t error_handler;
  70.   static one_arg_error_handler_t range_error_handler;
  71.  
  72.   static PEH overflow_handler;
  73.  
  74. public:
  75.           Fix();
  76.                   Fix(const Fix&);
  77.           Fix(double);
  78.                   Fix(int);
  79.                   Fix(int, const Fix&);
  80.                   Fix(int, double);
  81.  
  82.                   ~Fix();
  83.  
  84.   Fix             operator =  (const Fix&);
  85.   Fix             operator =  (double);
  86.  
  87.   friend int      operator == (const Fix&, const Fix&);
  88.   friend int      operator != (const Fix&, const Fix&);
  89.  
  90.   friend int      operator <  (const Fix&, const Fix&);
  91.   friend int      operator <= (const Fix&, const Fix&);
  92.   friend int      operator >  (const Fix&, const Fix&);
  93.   friend int      operator >= (const Fix&, const Fix&);
  94.  
  95.   Fix&            operator +  ();
  96.   Fix             operator -  ();
  97.  
  98.   friend Fix      operator +  (const Fix&, const Fix&);
  99.   friend Fix      operator -  (const Fix&, const Fix&);
  100.   friend Fix      operator *  (const Fix&, const Fix&);
  101.   friend Fix      operator /  (const Fix&, const Fix&);
  102.  
  103.   friend Fix      operator *  (const Fix&, int);
  104.   friend Fix      operator *  (int, const Fix&);
  105.   friend Fix      operator %  (const Fix&, int);
  106.   friend Fix      operator << (const Fix&, int);
  107.   friend Fix      operator >> (const Fix&, int);
  108.  
  109. #if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
  110.   friend Fix     operator <? (const Fix&, const Fix&); // min
  111.   friend Fix     operator >? (const Fix&, const Fix&); // max
  112. #endif
  113.  
  114.   Fix            operator += (const Fix&);
  115.   Fix            operator -= (const Fix&);
  116.   Fix            operator *= (const Fix&);
  117.   Fix            operator /= (const Fix&);
  118.  
  119.   Fix            operator *= (int);
  120.   Fix            operator %= (int);
  121.   Fix            operator <<=(int);
  122.   Fix            operator >>=(int);
  123.  
  124.   friend char*    Ftoa(const Fix&, int width = default_print_width);
  125.   void          printon(ostream&, int width = default_print_width) const;
  126.   friend Fix      atoF(const char*, int len = default_length);
  127.   
  128.   friend istream& operator >> (istream&, Fix&);
  129.   friend ostream& operator << (ostream&, const Fix&);
  130.  
  131.   // built-in functions
  132.   friend Fix      abs(Fix);             // absolute value
  133.   friend int      sgn(const Fix&);    // -1, 0, +1
  134.   friend Integer  mantissa(const Fix&);    // integer representation
  135.   friend double   value(const Fix&);    // double value
  136.   friend int      length(const Fix&);    // field length
  137.   friend void      show(const Fix&);    // show contents
  138.  
  139.   // error handlers
  140.   static void     error(const char* msg); // error handler
  141.   static void     range_error(const char* msg);    // range error handler
  142.  
  143.   static one_arg_error_handler_t set_error_handler(one_arg_error_handler_t f);
  144.   static one_arg_error_handler_t
  145.     set_range_error_handler(one_arg_error_handler_t f);
  146.  
  147.   static void      default_error_handler (const char *);
  148.   static void      default_range_error_handler (const char *);
  149.  
  150.   // non-operator versions for user
  151.   friend void      negate(const Fix& x, Fix& r);
  152.   friend void      add(const Fix& x, const Fix& y, Fix& r);
  153.   friend void      subtract(const Fix& x, const Fix& y, Fix& r);
  154.   friend void      multiply(const Fix& x, const Fix& y, Fix& r);
  155.   friend void      divide(const Fix& x, const Fix& y, Fix& q, Fix& r);
  156.   friend void      shift(const Fix& x, int y, Fix& r);
  157.  
  158.   // overflow handlers
  159.   static void overflow_saturate(Fix::Rep*);
  160.   static void overflow_wrap(Fix::Rep*);
  161.   static void overflow_warning_saturate(Fix::Rep*);
  162.   static void overflow_warning(Fix::Rep*);
  163.   static void overflow_error(Fix::Rep*);
  164.  
  165.   static PEH set_overflow_handler(PEH);
  166.  
  167.   static int set_default_length(int);
  168. };
  169.  
  170. // function definitions
  171.  
  172. inline void
  173. Fix::unique()
  174. {
  175.   if ( rep->ref > 1 )
  176.   {
  177.     rep->ref--;
  178.     rep = new_Fix(rep->len,rep);
  179.   }
  180. }
  181.  
  182. inline void
  183. Fix::mask (Fix::Rep* x)
  184. {
  185.   int n = x->len & 0x0f;
  186.   if ( n )
  187.     x->s[x->siz - 1] &= 0xffff0000 >> n; 
  188. }
  189.  
  190. inline Fix::Rep*
  191. Fix::copy(const Fix::Rep* from, Fix::Rep* to)
  192. {
  193.   _G_uint16_t *ts = to->s;
  194.   const _G_uint16_t *fs = from->s;
  195.   int ilim = to->siz < from->siz ? to->siz : from->siz;
  196.   for ( int i=0; i < ilim; i++ )
  197.     *ts++ = *fs++;
  198.   for ( ; i < to->siz; i++ )
  199.     *ts++ = 0;
  200.   mask(to);
  201.   return to;
  202. }
  203.  
  204. inline
  205. Fix::Fix(Rep* f)
  206. {
  207.   rep = f;
  208. }
  209.  
  210. inline
  211. Fix::Fix()
  212. {
  213.   rep = new_Fix(default_length);
  214. }
  215.  
  216. inline
  217. Fix::Fix(int len)
  218. {
  219.   if ( len < min_length || len > max_length )
  220.     error("illegal length in declaration");
  221.   rep = new_Fix((_G_uint16_t) len);
  222. }
  223.  
  224. inline
  225. Fix::Fix(double d)
  226. {
  227.   rep = new_Fix(default_length,d);
  228. }
  229.  
  230. inline
  231. Fix::Fix(const Fix&  y)
  232. {
  233.   rep = y.rep; rep->ref++;
  234. }
  235.  
  236. inline
  237. Fix::Fix(int len, const Fix&  y)
  238. {
  239.   if ( len < Fix::min_length || len > Fix::max_length )
  240.     error("illegal length in declaration");
  241.   rep = new_Fix((_G_uint16_t) len,y.rep);
  242. }
  243.  
  244. inline
  245. Fix::Fix(int len, const Rep* fr)
  246. {
  247.   if ( len < Fix::min_length || len > Fix::max_length )
  248.     error("illegal length in declaration");
  249.   rep = new_Fix((_G_uint16_t) len,fr);
  250. }
  251.  
  252. inline
  253. Fix::Fix(int len, double d)
  254. {
  255.   if ( len < Fix::min_length || len > Fix::max_length )
  256.     error("illegal length in declaration");
  257.   rep = new_Fix((_G_uint16_t) len,d);
  258. }
  259.  
  260. inline
  261. Fix::~Fix()
  262. {
  263.   if ( --rep->ref <= 0 ) delete rep;
  264. }
  265.  
  266. inline Fix
  267. Fix::operator = (const Fix&  y)
  268. {
  269.   if ( rep->len == y.rep->len ) {
  270.     ++y.rep->ref;
  271.     if ( --rep->ref <= 0 ) delete rep;
  272.     rep = y.rep; 
  273.   }
  274.   else {
  275.     unique();
  276.     copy(y.rep,rep);
  277.   }
  278.   return *this;
  279. }
  280.  
  281. inline Fix
  282. Fix::operator = (double d)
  283. {
  284.   int oldlen = rep->len;
  285.   if ( --rep->ref <= 0 ) delete rep;
  286.   rep = new_Fix(oldlen,d);
  287.   return *this;
  288. }
  289.  
  290. inline int
  291. operator == (const Fix&  x, const Fix&  y)
  292. {
  293.   return Fix::compare(x.rep, y.rep) == 0; 
  294. }
  295.  
  296. inline int
  297. operator != (const Fix&  x, const Fix&  y)
  298. {
  299.   return Fix::compare(x.rep, y.rep) != 0; 
  300. }
  301.  
  302. inline int
  303. operator <  (const Fix&  x, const Fix&  y)
  304. {
  305.   return Fix::compare(x.rep, y.rep) <  0; 
  306. }
  307.  
  308. inline int
  309. operator <= (const Fix&  x, const Fix&  y)
  310. {
  311.   return Fix::compare(x.rep, y.rep) <= 0; 
  312. }
  313.  
  314. inline int
  315. operator >  (const Fix&  x, const Fix&  y)
  316. {
  317.   return Fix::compare(x.rep, y.rep) >  0; 
  318. }
  319.  
  320. inline int
  321. operator >= (const Fix&  x, const Fix&  y)
  322. {
  323.   return Fix::compare(x.rep, y.rep) >= 0; 
  324. }
  325.  
  326. inline Fix&
  327. Fix::operator +  ()
  328. {
  329.   return *this;
  330. }
  331.  
  332. inline Fix
  333. Fix::operator -  ()
  334. {
  335.   Rep* r = negate(rep); return r;
  336. }
  337.  
  338. inline Fix
  339. operator +  (const Fix& x, const Fix& y)
  340. {
  341.   Fix::Rep* r = Fix::add(x.rep, y.rep); return r;
  342. }
  343.  
  344. inline Fix
  345. operator -  (const Fix& x, const Fix& y)
  346. {
  347.   Fix::Rep* r = Fix::subtract(x.rep, y.rep); return r;
  348. }
  349.  
  350. inline Fix
  351. operator *  (const Fix& x, const Fix& y)
  352. {
  353.   Fix::Rep* r = Fix::multiply(x.rep, y.rep); return r;
  354. }
  355.  
  356. inline Fix
  357. operator *  (const Fix& x, int y)
  358. {
  359.   Fix::Rep* r = Fix::multiply(x.rep, y); return r;
  360. }
  361.  
  362. inline Fix
  363. operator *  (int y, const Fix& x)
  364. {
  365.   Fix::Rep* r = Fix::multiply(x.rep, y); return r;
  366. }
  367.  
  368. inline Fix
  369. operator / (const Fix& x, const Fix& y)
  370. {
  371.   Fix::Rep* r = Fix::divide(x.rep, y.rep); return r;
  372. }
  373.  
  374. inline Fix
  375. Fix::operator += (const Fix& y)
  376. {
  377.   unique(); Fix::add(rep, y.rep, rep); return *this;
  378. }
  379.  
  380. inline Fix
  381. Fix::operator -= (const Fix& y)
  382. {
  383.   unique(); Fix::subtract(rep, y.rep, rep); return *this;
  384. }
  385.  
  386. inline Fix
  387. Fix::operator *= (const Fix& y)
  388. {
  389.   unique(); Fix::multiply(rep, y.rep, rep); return *this;
  390. }
  391.  
  392. inline Fix
  393. Fix::operator *= (int y)
  394. {
  395.   unique(); Fix::multiply(rep, y, rep); return *this;
  396. }
  397.  
  398. inline Fix
  399. Fix::operator /= (const Fix& y)
  400. {
  401.   unique(); Fix::divide(rep, y.rep, rep); return *this;
  402. }
  403.  
  404. inline Fix
  405. operator % (const Fix& x, int y)
  406. {
  407.   Fix r((int) x.rep->len + y, x); return r;
  408. }
  409.  
  410. inline Fix
  411. operator << (const Fix&  x, int y)
  412. {
  413.   Fix::Rep* rep = Fix::shift(x.rep, y); return rep;
  414. }
  415.  
  416. inline Fix
  417. operator >> (const Fix&  x, int y)
  418. {  
  419.   Fix::Rep* rep = Fix::shift(x.rep, -y); return rep;
  420. }
  421.  
  422. inline Fix
  423. Fix::operator <<= (int y)
  424. {
  425.   unique(); Fix::shift(rep, y, rep); return *this;
  426. }
  427.  
  428. inline Fix
  429. Fix::operator >>= (int y)
  430. {
  431.   unique(); Fix::shift(rep, -y, rep); return *this;
  432. }
  433.  
  434. #if defined (__GNUG__) && ! defined (__STRICT_ANSI__)
  435. inline Fix
  436. operator <? (const Fix& x, const Fix& y)
  437. {
  438.   if ( Fix::compare(x.rep, y.rep) <= 0 ) return x; else return y;
  439. }
  440.  
  441. inline Fix
  442. operator >? (const Fix& x, const Fix& y)
  443. {
  444.   if ( Fix::compare(x.rep, y.rep) >= 0 ) return x; else return y;
  445. }
  446. #endif
  447.  
  448. inline Fix
  449. abs(Fix  x)
  450. {
  451.   Fix::Rep* r = (Fix::compare(x.rep) >= 0 ? Fix::new_Fix(x.rep->len,x.rep) :
  452.          Fix::negate(x.rep));
  453.   return r;
  454. }
  455.  
  456. inline int
  457. sgn(const Fix& x)
  458. {
  459.   int a = Fix::compare(x.rep);
  460.   return a == 0 ? 0 : (a > 0 ? 1 : -1);
  461. }
  462.  
  463. inline int
  464. length(const Fix& x)
  465. {
  466.   return x.rep->len;
  467. }
  468.  
  469. inline ostream&
  470. operator << (ostream& s, const Fix& y)
  471. {
  472.   if (s.opfx())
  473.     y.printon(s);
  474.   return s;
  475. }
  476.  
  477. inline void
  478. negate (const Fix& x, Fix& r)
  479. {
  480.   Fix::negate(x.rep, r.rep);
  481. }
  482.  
  483. inline void
  484. add (const Fix& x, const Fix& y, Fix& r)
  485. {
  486.   Fix::add(x.rep, y.rep, r.rep);
  487. }
  488.  
  489. inline void
  490. subtract (const Fix& x, const Fix& y, Fix& r)
  491. {
  492.   Fix::subtract(x.rep, y.rep, r.rep);
  493. }
  494.  
  495. inline void
  496. multiply (const Fix& x, const Fix& y, Fix& r)
  497. {
  498.   Fix::multiply(x.rep, y.rep, r.rep);
  499. }
  500.  
  501. inline void
  502. divide (const Fix& x, const Fix& y, Fix& q, Fix& r)
  503. {
  504.   Fix::divide(x.rep, y.rep, q.rep, r.rep);
  505. }
  506.  
  507. inline void
  508. shift (const Fix& x, int y, Fix& r)
  509. {
  510.   Fix::shift(x.rep, y, r.rep);
  511. }
  512.  
  513. #endif
  514.